﻿using UnityEngine;

namespace Obi.Samples
{
    [RequireComponent(typeof(ObiRope))]
    public class HosePump : MonoBehaviour
    {

        [Header("Bulge controls")]
        public float pumpSpeed = 5;
        public float bulgeFrequency = 3;
        public float baseThickness = 0.04f;
        public float bulgeThickness = 0.06f;
        public Color bulgeColor = Color.cyan;

        [Header("Flow controls")]
        public ParticleSystem waterEmitter;
        public float flowSpeedMin = 0.5f;
        public float flowSpeedMax = 7;
        public float minEmitRate = 100;
        public float maxEmitRate = 1000;

        private ObiRope rope;
        public ObiPathSmoother smoother;
        private float time = 0;

        void OnEnable()
        {
            rope = GetComponent<ObiRope>();
            smoother = GetComponent<ObiPathSmoother>();
            rope.OnSimulationStart += Rope_OnBeginStep;
        }
        void OnDisable()
        {
            rope.OnSimulationStart -= Rope_OnBeginStep;
        }

        private void Rope_OnBeginStep(ObiActor actor, float stepTime, float substepTime)
        {
            time += stepTime * pumpSpeed;

            float distance = 0;
            float sine = 0;

            // iterate over all particles, changing their radius and color based on a sine wave:
            // (note this would not support resizable / cuttable ropes, to add support for that use rope.elements instead)
            for (int i = 0; i < rope.solverIndices.count; ++i)
            {
                int solverIndex = rope.solverIndices[i];

                if (i > 0)
                {
                    int previousIndex = rope.solverIndices[i - 1];
                    distance += Vector3.Distance(rope.solver.positions[solverIndex], rope.solver.positions[previousIndex]);
                }

                sine = Mathf.Max(0, Mathf.Sin(distance * bulgeFrequency - time));

                rope.solver.principalRadii[solverIndex] = Vector3.one * Mathf.Lerp(baseThickness, bulgeThickness, sine);
                rope.solver.colors[solverIndex] = Color.Lerp(Color.white, bulgeColor, sine);
            }

            // change particle emission rate/speed based on sine wave at the last particle:
            if (waterEmitter != null)
            {
                var main = waterEmitter.main;
                main.startSpeed = Mathf.Lerp(flowSpeedMin, flowSpeedMax, sine);

                var emission = waterEmitter.emission;
                emission.rateOverTime = Mathf.Lerp(minEmitRate, maxEmitRate, sine);
            }
        }

        public void LateUpdate()
        {
            if (smoother != null && waterEmitter != null)
            {
                ObiPathFrame section = smoother.GetSectionAt(1);
                waterEmitter.transform.position = rope.solver.transform.TransformPoint(section.position);
                waterEmitter.transform.rotation = rope.solver.transform.rotation * (Quaternion.LookRotation(section.tangent, section.binormal));
            }
        }
    }
}
